package com.neusoft.chatserver.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.neusoft.chatserver.entity.Message;
import com.neusoft.chatserver.service.IChatGroupService;
import com.neusoft.chatserver.service.IMessageService;
import com.neusoft.chatserver.service.impl.MessageServiceImpl;
import com.neusoft.chatserver.tool.EmojiFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

@CrossOrigin
@RestController
@ServerEndpoint(value = "/websocket/{userId}")
public class ChatWebSocket {
    private static IMessageService iMessageService;


    @Autowired
    public void setiMessageService(IMessageService iMessageService) {
        ChatWebSocket.iMessageService = iMessageService;
    }

    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    //concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话，可以使用Map来存放，其中Key可以为用户标识
    private static ConcurrentHashMap<Integer, ChatWebSocket> webSocketSet = new ConcurrentHashMap();
    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session WebSocketsession;
    //当前发消息的人员编号
    private Integer userId;


    /**
     * 连接建立成功调用的方法
     *
     * session 可选的参数。session为与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(@PathParam(value = "userId") Integer userId, Session WebSocketsession) {
        this.userId = userId;//接收到发送消息的人员编号
        this.WebSocketsession = WebSocketsession;
        webSocketSet.put(userId, this);//加入map中
        addOnlineCount();     //在线数加1
        //System.out.println("有新连接加入！当前在线人数为" + getOnlineCount());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if (userId != null) {
            webSocketSet.remove(userId); //从set中删除
            subOnlineCount();     //在线数减1
            //System.out.println("有一连接关闭！当前在线人数为" + getOnlineCount());
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param chatmsg 客户端发送过来的消息
     * @param session 可选的参数
     */
    @OnMessage
    public void onMessage(String chatmsg, Session session) {
        JSONObject jsonObject = JSONObject.parseObject(chatmsg);
        //给指定的人发消息
        Message message = jsonObject.toJavaObject(Message.class);
        sendToUser(message);
        //sendAll(message);
    }

//    private void sendToGroup(Message message) {
//        Integer toUser = message.getMsgTo();
//        String content = message.getMsgContent();
//        content= EmojiFilter.filterEmoji(content);//过滤输入法输入的表情
//        message.setMsgContent(content);
//        message.setMsgFrom(userId);
//        //todo
//    }


    /**
     * 给指定的人发送消息
     *
     */
    public void sendToUser(Message message) {
        Integer toUser = message.getMsgTo();
        String content = message.getMsgContent();
        content= EmojiFilter.filterEmoji(content);//过滤输入法输入的表情
        message.setMsgContent(content);
        message.setMsgFrom(userId);
        iMessageService.addMessage(message);
        try {
            if (webSocketSet.get(toUser) != null) {
                webSocketSet.get(toUser).sendMessage(message);
            }else{
                webSocketSet.get(userId).sendMessage("0"+"|"+"当前用户不在线");
            }
        } catch (IOException | EncodeException e) {
            e.printStackTrace();
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }


    public static synchronized void addOnlineCount() {
        ChatWebSocket.onlineCount++;
    }

    /**
     * 这个方法与上面几个方法不一样。没有用注解，是根据自己需要添加的方法。
     *
     * @param message
     * @throws IOException
     */
    public void sendMessage(Message message) throws IOException, EncodeException {
        this.WebSocketsession.getBasicRemote().sendText(JSON.toJSONString(message));
        //this.session.getAsyncRemote().sendText(message);
    }
    public void sendMessage(String message) throws IOException, EncodeException {
        this.WebSocketsession.getBasicRemote().sendText(message);
        //this.session.getAsyncRemote().sendText(message);
    }
    public static synchronized void subOnlineCount() {
        ChatWebSocket.onlineCount--;
    }

}
